package jut.concurrent.concurrent.Atomic;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

public class AbaDemo {

	static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
	static AtomicStampedReference<Integer> atomicStampedReference = new  AtomicStampedReference<Integer>(100, 1);

	public static void main(String[] args) {
		new Thread(()->{
			atomicReference.compareAndSet(100,200);
			atomicReference.compareAndSet(200,100);
		},"t1").start();
		
		new Thread(()->{
			
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			System.out.print(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());
			
		},"t2").start();
		
		
		System.out.println("==================以下是ABA问题的解决");
		
		new Thread(()->{
			int stamp = atomicStampedReference.getStamp();
			System.out.println(Thread.currentThread().getName()+"\t第一次版本号："+stamp);
			
			
			//暂停一秒
			try {
				TimeUnit.SECONDS.sleep(3);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			atomicStampedReference.compareAndSet(100, 200, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
			System.out.println(Thread.currentThread().getName()+"\t第二次版本号："+stamp);
			atomicStampedReference.compareAndSet(200, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
			System.out.println(Thread.currentThread().getName()+"\t第三次版本号："+stamp);
		},"t3").start();
		

		new Thread(()->{
			int stamp = atomicStampedReference.getStamp();
			System.out.println(Thread.currentThread().getName()+"\t第一次版本号："+stamp);
			
			
			//暂停一秒
			try {
				TimeUnit.SECONDS.sleep(3);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			boolean result = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp+1);
			System.out.println(Thread.currentThread().getName()+"\t修改成功？"+result+"\t当前最新实际版本号"+atomicStampedReference.getStamp());
			System.out.println(Thread.currentThread().getName()+"\t当前实际最新值"+atomicStampedReference.getReference());
		},"t4").start();
	}
}
